<template>
  <el-form-item :class="getClz(['upload-img','autoheight',opt.className])" :label="opt.text" :prop="opt.name" v-if="!opt.hide" size="mini">
    <el-upload
      class="upload-demo" :accept="opt.props.accept" :disabled="opt.props.disabled"
      action="="
      :before-upload="handleBefore"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      multiple
      :limit="opt.limit"
      :on-exceed="handleExceed"
      :show-file-list="opt.showFile"
      :file-list="fileList"
      :http-request="upload"
    >
      <el-button size="mini" type="primary" :loading="opt.loading">{{opt.buttonText}}</el-button>
      <div slot="tip" class="el-upload__tip" v-show="Boolean(opt.showTips)">{{opt.showTips}}</div>
    </el-upload>
  </el-form-item>
</template>

<script>
  import extend from '../extend';

  const defaultOpt = {
    loading:false,
    showTips:"",
    showFile:true,
    name:'',
    text:'',
    className:'',
    fileSize:3, // M
    limit:1,
    buttonText:"上传文件",
    params:{path:"img"},
    props:{
      accept:'',
      disabled:false
    }
  }

  export default {
    name: "FormUpload",
    mixins:[extend],
    data(){
      return {
        showFile:false,
        fileList:[],
        opt:{...defaultOpt}
      }
    },
    created(){
      this.nextUpload = _.debounce(nextUpload.bind(this),300)
    },
    methods: {
      setOpt(conf) {
        _.assign(this.opt, conf);
        this.showFile = this.opt.showFile;
        this.setValue(conf.value);
      },
      setValue(list) {
        let res = this.setValueMap(list);
        this.fileList = res;
        this.$forceUpdate();
      },
      setValueMap(list = []) {
        if (Object.prototype.toString.call(list) == "[object String]") {
          list = [{name: list.replace(/.*\/(.*)/, '$1'), url: list}]
        }
        //
        if(this.column.limit == 1){
          this.data[this.opt.name] = list.length<1 ? '' : list[0]?.url;
        }else{
          this.data[this.opt.name] = list;
        }
        return list;
      },
      handleBefore(file) {
        let opt = this.opt;
        let isOk = file.size / 1024 / 1024 < opt.fileSize;
        let acceptArr = opt.props.accept?opt.props.accept.split(","):[];
        //
        if(acceptArr.length){
          let error = true;
          acceptArr.every((v)=>{
            let str = v.split("/");
            let valStr = (file.type||"").split('/');
            if(str[1] == "*" && str[0] == valStr[0]){
              error = false;
            }else if(v.indexOf(file.type)>-1){
              error = false;
            }
            return error;
          })
          //
          if(error){
            this.$message.warning(`文件类型不支持！(仅支持：${opt.props.accept})`);
            return false;
          }
        }
        //
        if (file.size < 1) {
          this.$message.warning(`上传文件过小！`);
          return false;
        } else if (!isOk) {
          this.$message.warning(`上传文件大小不能超过${opt.fileSize}MB!`);
        }
        return isOk;
      },
      handleRemove(file) {
        let idx = _.findIndex(this.fileList, file);
        if(idx>-1){
          this.fileList.splice(idx, 1);
          this.setValueMap(this.fileList);
        }
      },
      handlePreview: (file) => {
        //console.log(file);
        window.open(file.url);
      },
      handleExceed(files, fileList) {
        this.$message.warning(`当前限制选择 ${this.opt.limit}个文件`);
      },
      upload({file}) {
        let onUpload = this.opt.onUpload;
        const blob = new Blob([file], {type: file.type});
        const row = {name: file.name, url: '',file:file,status:"uploading",percentage:80}; // 'success', 'error', 'uploading'
        //const fileUrl = window.URL.createObjectURL(blob);
        this.fileList.push(row);
        this.setValueMap(this.fileList);
        if("flowUpload" === onUpload){
          this.nextUpload();
        }else{
          upload.call(this,row)
        }
      }
    }
  }

  // 上传
  function upload(row,callback = ()=>{}){
    let file = row.file;
    let params = {file,...this.opt.params};
    let ajaxPro = typeof this.opt.onUpload == 'function'? this.opt.onUpload(params):this.api("base.upload",params);
    row.file = void 0;
    row.ajax = true;
    ajaxPro.then((res)=>{
      let data = res;
      row.name = file.name;
      row.url = data.url;
      row.originPath = data.url;
      row.smallUrl = data.smallUrl;
      row.id = data.imgId;
      row.yzImgId = data.yzImgId;
      row.imgType = params.imgTypeEnum;
      row.status = "success";
    },()=>{
      row.status = "error";
    }).finally(()=>{
      this.fileList.splice(0,0)
      row.ajax = false;
      callback(row);
    })
  }

  // 因为后端无法排序：只能顺序上传
  function nextUpload(){
    let sc = this;
    let exec = function(i){
      let fileList = sc.fileList;
      let row = fileList[i];
      if(!row || row.ajax){
        return;
      }
      // 执行下一个
      if(row.file){
        upload.call(sc,row,()=>{
          exec(i+1)
        })
      }else{
        exec(i+1)
      }
    }
    //
    exec(0)
  }
</script>

<style lang="scss">
  .upload-demo{
    .el-icon-close-tip{
      display:none;
    }

    .el-upload-list__item.is-error .el-upload-list__item-name{
      color:red;

      &::after{
        content:" 上传失败 "
      }
    }
  }
</style>
